package club.janna.hello.util;

import org.apache.commons.beanutils.PropertyUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

/**
 * 通用工具类
 */
public class CommonUtil {

    /**
     * Map转对象
     */
    public static Object ConvertMapToObj(Map map, Class c) {
        if (c != null) {
            Object obj;
            try {
                obj = c.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("初始化类异常：" + e.getMessage());
            }
            //需要获取子类和父类信息
            Map<String,List<?>> temp = getMethods(obj);
            List<Field> fieldList = (List<Field>)temp.get("field");
            Field[] fields = fieldList.toArray(new Field[fieldList.size()]);
            for (int i = 0; i < fields.length; i++) {
                try {
                    if (map.containsKey(fields[i].getName())) {
                        Object o = convertToValidType(map.get(fields[i].getName()), fields[i]
                                .getType());
                        setProperty(obj, fields[i].getName(), o);
                    }
                } catch (Exception e) {
                }
            }
            return obj;
        }
        return null;
    }

    /**
     * 获取对象所有的方法和属性 包括其父类
     * @param o
     * @return  key :method, field  value: list<Method>  ,list<Field>
     */
    public static  Map<String,List<?>> getMethods(Object o){
        Map<String,List<?>> resMap = new HashMap<String,List<?>>();
        List<Method> methodList = new ArrayList<Method>();
        List<Field> fieldList = new ArrayList<Field>();
        resMap.put("method", methodList);
        resMap.put("field", fieldList);

        //添加方法
        Method[] method = o.getClass().getDeclaredMethods();
        methodList.addAll(Arrays.asList(method));
        //添加属性
        Field[] field = o.getClass().getDeclaredFields();
        fieldList.addAll(Arrays.asList(field));

        Class<?> parent = o.getClass().getSuperclass();
        while(parent != null){
            //添加方法
            method = parent.getDeclaredMethods();
            methodList.addAll(Arrays.asList(method));
            //添加属性
            field = parent.getDeclaredFields();
            fieldList.addAll(Arrays.asList(field));
            parent = parent.getSuperclass();
        }
        return resMap;
    }
    /**
     *
     * @author yzy
     * @date 2018-1-03
     * @param o object
     * @param type
     * @return
     */
    private static Object convertToValidType(Object o, Class<?> type) {
        if (o == null || type == null) {
            return null;
        }
        if (String.class.equals(type)) {
            return o.toString();
        } else if (long.class.equals(type)) {
            return Long.parseLong(o.toString());
        } else if (int.class.equals(type)) {
            return Integer.parseInt(o.toString());
        }else if(float.class.equals(type)){
            return Float.parseFloat(o.toString());
        } else if (double.class.equals(type)) {
            return Double.parseDouble(o.toString());
        } else if (BigDecimal.class.equals(type)) {
            return new BigDecimal(o.toString());
        }else if (Timestamp.class.equals(type)) {
            return o;
        }
        return null;
    }

    /**
     * 设置对象属性
     *
     * @param obj
     * @param propertyName
     * @param value
     * @throws Exception
     */
    public static void setProperty(Object obj, String propertyName, Object value) {
        try {
            if (obj instanceof Map) {
                ((Map) obj).put(propertyName, value);
            } else {
                PropertyDescriptor des = PropertyUtils.getPropertyDescriptor(
                        obj, propertyName);
                if (des.getWriteMethod() == null) {
                    return;
                }
                if (des != null && propertyName != null) {
                    des.getWriteMethod().invoke(obj, value);
                }
            }
        } catch (Exception e) {
        }
    }
}